#include "FileIO.h"
#include <fstream>
#include <iostream>
#include <vector>
#include <ctime>
#include "../common_typedef.h"

static long startClock;
int FileIO::TxCsvToCom(string& portName, const string& filePath)
{
    /* 开始计时 */
    startClock = clock();
    cout << "TxCsvToCom TxFile [" << filePath << "] to port<" << portName << ">" << endl;
    vector<uint8_t> txData;
    /* 从文件中获取数据 */
    int ret = ExtractCsv(filePath, txData);
    if (ret != ERR_SUCCESS) {
        return ret;
    }
    /* 打开串口并发送 */
    ret = TxCom(portName, txData.data(), txData.size());
    if (ret != ERR_SUCCESS) {
        return ret;
    }
    return ERR_SUCCESS;
}


int FileIO::ExtractCsv(const string& filePath, vector<uint8_t>& txData)
{
    ifstream txSrc(filePath);
    txData.clear();
    if (!txSrc.is_open()) {
        cout << "File " << filePath << " open failed." << endl;
        return ERR_FAILURE;
    }
    string txSrcLine;
    while (getline(txSrc, txSrcLine)) {
        txData.push_back(stoi(txSrcLine));
    }

    return ERR_SUCCESS;
}

#include <Windows.h>
int FileIO::TxCom(string& portName, const uint8_t* data, size_t len)
{
    /* 打开串口并发送 */
    portName = "//./" + portName; // 恢复原始路径
    auto comHandle = ::CreateFile(portName.c_str(), GENERIC_WRITE | GENERIC_READ,
                                  0, nullptr, OPEN_EXISTING,
                                  FILE_ATTRIBUTE_NORMAL, nullptr);
    if (comHandle == INVALID_HANDLE_VALUE) {
        cout << "port " << portName << " open failed." << endl;
        return ERR_FAILURE;
    }
    DCB dcb;
    SecureZeroMemory(&dcb, sizeof(DCB));
    if (!GetCommState(comHandle, &dcb)) {
        cout << "port " << portName << " cannt get status." << endl;
        return ERR_FAILURE;
    }
    dcb.BaudRate = 115200;
    dcb.ByteSize = 8;
    dcb.fParity = NOPARITY;
    dcb.Parity = NOPARITY;
    dcb.StopBits = 1;
    dcb.fInX = 0;
    dcb.fOutX = 0;
    dcb.fOutxCtsFlow = 0;
    dcb.fRtsControl = 0;
    auto err = SetCommState(comHandle, &dcb);
    if (!err) {
        cout << "port " << portName << " cannt be set." << endl;
        (void)CloseHandle(comHandle);
        return ERR_FAILURE;
    }
    unsigned long txedLen = 0;
    uint32_t errCode = WriteFile(comHandle, data, len, &txedLen, nullptr);
    if (errCode == 0) {
        cout << "port " << portName << " writing Failed." << endl;
        return ERR_FAILURE;
    }

    (void)CloseHandle(comHandle);
    cout << "TxCsvToCom Done in " << clock() - startClock << " ms" << endl;

    return ERR_SUCCESS;
}

/* 打印内存值 */
void PutRam(const uint8_t* data, size_t len)
{
    auto p = data;
    for (size_t idx = 0; idx < len; idx++) {
        cout << *p << ", ";
        if (idx % 8 == 0) {
            cout << " ";
        }
        if (idx % 16 == 0) {
            cout << endl;
        }
    }
}